#include "app_message.h"



//二进制串解析为消息
message* app_message_initFromBinary(void *data, size_t len){
    if (len <= 3){
        log_warn("data len is too short");
        return NULL;
    }

    message *msg = (message*)malloc(sizeof(message));
    if (!msg){
        log_error("malloc message fail");
        goto MSG_ALLOC_FAIL;
    }
    memset(msg, 0, sizeof(message));

    memcpy(&msg->type, data, 1);
    memcpy(&msg->id_len, data + 1, 1);
    memcpy(&msg->len, data + 2, 1);

    //动态分配id内存
    msg->id = malloc(msg->len);
    if (!msg->id){
        log_error("malloc message id fail");
        goto ID_ALLOC_FAIL;
    };
    msg->data = malloc(msg->len);
    if (!msg->data){
        log_error("malloc message data fail");
    
        goto DATA_ALLOC_FAIL;
    }

    memcpy(msg->id, data + 3, msg->id_len);
    memcpy(msg->data, data + 3 + msg->id_len, msg->len);
    
    log_debug("message init success type:%d, id_len:%d, len:%d, id:%s, data:%s" , msg->type, msg->id_len, msg->len, msg->id, msg->data);
    return msg;

DATA_ALLOC_FAIL:
    free(msg->id);
ID_ALLOC_FAIL:
    free(msg);
MSG_ALLOC_FAIL:
    return NULL;
}
static unsigned char app_message_hexChar2hex(char hex_char)
{
    if (hex_char >= '0' && hex_char <= '9')
    {
        return hex_char - '0';
    }
    else if (hex_char >= 'a' && hex_char <= 'f')
    {
        return hex_char - 'a' + 10;
    }
    else if (hex_char >= 'A' && hex_char <= 'F')
    {
        return hex_char - 'A' + 10;
    }
    else
    {
        log_error("Invalid hex char");
        return 0;
    }
}
//将字符串转化为二进制
static void app_message_str2hex(char *str, void *hex_ptr, size_t hex_len){

    unsigned char *temp_ptr = hex_ptr;
    for (size_t i = 0; i < hex_len; i++){
        temp_ptr[i] = 0;
        temp_ptr[i] += app_message_hexChar2hex(str[2 * i]);
        temp_ptr[i] <<= 4;
        temp_ptr[i] += app_message_hexChar2hex(str[2 * i + 1]);
    }
}

//Json解析
message* app_message_initFromJson(char *json_str, size_t len){
    cJSON *root_object = cJSON_ParseWithLength(json_str, len);

    if (!root_object){
        log_error("parse json fail");
        goto JSON_PARSE_FAIL;
    }

    message *msg = (message*)malloc(sizeof(message));

    if (!msg){
        log_error("malloc message fail");
        goto MSG_ALLOC_FAIL;
    }
    memset(msg, 0, sizeof(message));

    cJSON *connection_type_ojb = cJSON_GetObjectItem(root_object, "connection_type");
    if (!cJSON_IsNumber(connection_type_ojb)){
        log_error("connection_type is not number");
        goto JSON_NOT_VALID;
    }

    msg->type = connection_type_ojb->valueint;

    cJSON *id_obj = cJSON_GetObjectItem(root_object, "id");
    if (!cJSON_IsString(id_obj)){
        log_error("id is not string");
        goto JSON_NOT_VALID;
    }

    cJSON *msg_obj = cJSON_GetObjectItem(root_object, "data");
    if (!cJSON_IsString(msg_obj)){
        log_error("data is not string");
        goto JSON_NOT_VALID;
    }

    msg->id_len = strlen(id_obj->valuestring) / 2;
    msg->len = strlen(msg_obj->valuestring) / 2;

    msg->id = malloc(msg->id_len);
    if (!msg->id){
        log_error("malloc message id fail");
        goto ID_ALLOC_FAIL;
    }

    msg->data = malloc(msg->len);
    if (!msg->data){
        log_error("malloc message data fail");
        goto DATA_ALLOC_FAIL;
    }

    app_message_str2hex(id_obj->valuestring, msg->id, msg->id_len);

    app_message_str2hex(msg_obj->valuestring, msg->data, msg->len);

    free(root_object);
    log_info("message init success");
    return msg;

DATA_ALLOC_FAIL:
    free(msg->id);
ID_ALLOC_FAIL:
JSON_NOT_VALID:
    free(msg);
MSG_ALLOC_FAIL:
    cJSON_Delete(root_object);
JSON_PARSE_FAIL:
    return NULL;
}


//消息转化为字符串
static char *app_message_hex2str(void *hex_ptr, size_t hex_len){
    char *str = (char *)malloc(hex_len * 2 + 1);
    if (!str){
        log_error("malloc str fail");
        return NULL;
    }

    unsigned char *temp_ptr = hex_ptr;

    for (size_t i = 0; i < hex_len; i++){
        sprintf(str + i * 2, "%02x", temp_ptr[i]);
    }

    str[hex_len * 2] = '\0';
    return str;
}
//消息转化为json
int app_message_saveAsJson(message *msg, char *json_str, size_t len){
    if (!msg || !json_str){
        log_warn("message or json_str is NULL");
        return -1;
    }

    cJSON *root_object = cJSON_CreateObject();
    if (!root_object){
        log_error("create json object fail");
        goto JSON_CREATE_FAIL;
    }

    cJSON_AddNumberToObject(root_object, "connection_type", msg->type);

    char *id_str = app_message_hex2str(msg->id, msg->id_len);
    if (!id_str){
        log_error("hex2str fail");
        goto ID_STR_NEW_FAIL;
    }

    char *data_str = app_message_hex2str(msg->data, msg->len);
    if (!data_str){
        log_error("hex2str fail");
        goto DATA_STR_NEW_FAIL;
    }

    cJSON_AddStringToObject(root_object, "id", id_str);
    cJSON_AddStringToObject(root_object, "data", data_str);
    char *temp_str = cJSON_PrintUnformatted(root_object);
    if (strlen(temp_str) > len){
        log_error("Out buffer not enough");
        goto OUT_BUFFER_NOT_ENOUGH;
    }
    strcpy(json_str, temp_str);
    
    cJSON_Delete(root_object);

    log_info("Save message to json success");

    return strlen(json_str) + 1;

OUT_BUFFER_NOT_ENOUGH:
    free(data_str);
DATA_STR_NEW_FAIL:
    free(id_str);
ID_STR_NEW_FAIL:
    cJSON_Delete(root_object);
JSON_CREATE_FAIL:
    return -1;
}

//消息转化为二进制串
int app_message_saveAsBinary(message *msg, void *data, size_t len){
    if (len < 3 + msg->len + msg->id_len){
        
        log_warn("data len is too short");
        return -1;
    }

    memcpy(data, &msg->type, 1);
    memcpy(data + 1, &msg->id_len, 1);
    memcpy(data + 2, &msg->len, 1);
    
    memcpy(data + 3, msg->id, msg->id_len);
    memcpy(data + 3 + msg->id_len, msg->data, msg->len);

    log_info("Save message to binary success");
    return 3 + msg->id_len + msg->len;
}
//释放消息
void app_message_free(message *msg){
    free(msg->id);
    free(msg->data);
    free(msg);
}